<template>
  <div class="license-agreement">
    <ContentContainer
      :show-pagination="false"
      :show-footer="false"
      :loading="loading"
      inner
      :refresh="false">
      <div class="flex flex-col gap-y-6">
        <div class="flex flex-col gap-y-2">
          <span class="title">证书模式</span>
          <a-radio-group v-model="source">
            <a-radio :value="2">
              <div class="flex items-center">
                <span>系统托管</span>
                <a-tag color="#14AF9C" class="system-tag">自动续期</a-tag>
              </div>
            </a-radio>
            <a-radio :value="1">手动上传</a-radio>
          </a-radio-group>
        </div>
        <ManualUpload v-if="source === 1" />
        <SystemHosting v-else :cname="cname" @reload="getLicenseInfo" />
        <div class="flex flex-col">
          <span class="title">协议选择</span>
          <!-- <span class="subtitle">
            HTTP 端口：{{ httpPortList.join(',') }}，HTTPS 端口：{{
              httpsPortList.join(',')
            }}
          </span> -->
          <div class="agreement-array">
            <div class="agreement-array-row" v-if="httpPortListTop3.length">
              <div class="agreement-array-key">HTTP 端口：</div>
              <div class="agreement-array-value">
                <div
                  v-for="item in httpPortListTop3"
                  :key="item"
                  class="agreement-array-item">
                  {{ item }}
                </div>
                <a-tooltip
                  position="top"
                  trigger="hover"
                  background-color="#fff"
                  content-class="custom-tooltip">
                  <template #content>
                    <div
                      v-for="item in httpPortListOther"
                      :key="item"
                      class="agreement-array-item">
                      {{ item }}
                    </div>
                  </template>
                  <div
                    v-if="httpPortList.length > 3"
                    class="agreement-array-item agreement-more">
                    ···
                  </div>
                </a-tooltip>
              </div>
            </div>
            <div class="agreement-array-row" v-if="httpsPortListTop3.length">
              <div class="agreement-array-key">HTTPS 端口：</div>
              <div class="agreement-array-value">
                <div
                  v-for="item in httpsPortListTop3"
                  :key="item"
                  class="agreement-array-item">
                  {{ item }}
                </div>
                <a-tooltip
                  position="top"
                  trigger="hover"
                  background-color="#fff"
                  content-class="custom-tooltip">
                  <template #content>
                    <div
                      v-for="item in httpsPortListOther"
                      :key="item"
                      class="agreement-array-item">
                      {{ item }}
                    </div></template
                  >
                  <div
                    v-if="httpsPortList.length > 3"
                    class="agreement-array-item agreement-more">
                    ···
                  </div>
                </a-tooltip>
              </div>
            </div>
          </div>
          <div class="agreement-content">
            <div class="agreement-content-left">
              <a-radio-group
                v-model="protocol"
                direction="vertical"
                @click="
                  (e: any) => {
                    if (e.target?.className === 'change-port') {
                      e.preventDefault()
                    }
                  }
                ">
                <a-radio
                  v-for="item in protocolArray"
                  :key="item.value"
                  :value="item.value"
                  class="mt-4 w-fit">
                  <div class="flex">
                    <div class="title">{{ item.title }}</div>
                  </div>
                </a-radio>
              </a-radio-group>
            </div>
            <div class="agreement-content-right">
              <a-radio-group v-model="protocol" direction="vertical">
                <div
                  v-for="(item, index) in protocolArray"
                  :key="item.value"
                  :value="item.value"
                  class="mt-4 w-fit">
                  <div class="flex">
                    <div class="subtitle text-xs!">
                      {{ `${item.subtitle}`
                      }}<template v-if="index === 2"
                        >，目标端口：
                        <span>
                          <a-input-number
                            v-show="showPortInput"
                            ref="portInputRef"
                            v-model="port"
                            :precision="0"
                            :max-length="5"
                            :min="0"
                            :max="65535"
                            hide-button
                            class="w-15! px-2! h-6! border-1"
                            @press-enter="handleBlur"
                            @blur="handleBlur">
                          </a-input-number>
                          <span
                            v-if="!showPortInput"
                            class="change-port"
                            @click="show"
                            >{{ port }}</span
                          >
                        </span>
                      </template>
                    </div>
                  </div>
                </div>
              </a-radio-group>
            </div>
          </div>
        </div>
      </div>
      <a-button
        type="primary"
        class="mt-6"
        :loading="saveLoading"
        @click="handleSave">
        保存配置
      </a-button>
    </ContentContainer>
    <ContentContainer
      :show-pagination="false"
      :show-footer="false"
      :refresh="false"
      inner>
      <div class="font-bold text-1 text-sm/22px">HSTS 配置</div>
      <div class="flex items-center gap-x-6px mb-6">
        <span class="text-xs/5 text-5">
          强制浏览器通过 HTTPS 协议请求站点。
        </span>
        <a-tooltip placement="top" :content-style="{ 'max-width': '454px' }">
          <template #content>
            <div class="text-sm/22px">
              1.开启 HSTS，需浏览器通过 HTTPS 访问一次站点后生效。<br />
              2.由于 HSTS 配置在浏览器，关闭 HSTS
              后无法立即生效，需要清理浏览器缓存或者缓存过期后才会生效。
            </div>
          </template>
          <i-icons-question class="question-icon" />
        </a-tooltip>
      </div>
      <a-switch
        v-if="licenseInfo.site_cert?.hsts_status"
        :model-value="licenseInfo.site_cert?.hsts_status"
        :checked-value="1"
        :unchecked-value="2"
        size="small"
        :before-change="
          (val: number) => handleBeforeChange(val, licenseInfo.site_cert)
        "></a-switch>
    </ContentContainer>
    <ContentContainer
      :show-pagination="false"
      :show-footer="false"
      inner
      :refresh="false">
      <template #header>
        <div class="flex flex-col">
          <span class="title font-bold text-1">支持协议版本</span>
        </div>
      </template>
      <div class="flex gap-x-6">
        <div v-for="item in tlsArray" :key="item" class="flex gap-x-2">
          <i-icons-success />
          {{ item }}
        </div>
      </div>
    </ContentContainer>
    <UploadLicense
      v-model="visible"
      :record="data"
      @reload="getLicenseInfo"></UploadLicense>
  </div>
</template>
<script setup lang="ts">
import type { SiteLicenseCname, SiteLicenseModel } from '@/apis/model/license'
import { getApiConfigHttpPortsApi } from '@/apis/modules/config'
import {
  getApiSiteCertApi,
  updateApiSiteCertApi,
  updateApiSiteCertHstsApi
} from '@/apis/modules/license'
import type { InputInstance } from '@arco-design/web-vue'
import ManualUpload from './components/ManualUpload.vue'
import SystemHosting from './components/SystemHosting.vue'
import UploadLicense from './components/UploadLicense.vue'
const { visible, open: openUpload, data } = usePopup()

const loading = ref(false)
const route = useRoute()
const source = ref(2)
const protocol = ref(1)
const port = ref(443)
const httpPortList = ref<string[]>([])
const httpsPortList = ref<string[]>([])
const portInputRef = ref<InputInstance[]>([])
const licenseInfo = ref<SiteLicenseModel>({})
const cname = ref<SiteLicenseCname>()
const siteId = computed(() => route.params.id as string)
const showPortInput = ref(false)
const protocolArray = [
  {
    title: '仅HTTP',
    subtitle: '只能通过 HTTP 请求站点',
    value: 1
  },
  {
    title: 'HTTP+HTTPS',
    subtitle: '可同时通过 HTTP 和 HTTPS 请求站点',
    value: 2
  },
  {
    title: '强制HTTPS',
    subtitle: '将所有 HTTP 请求重定向到 HTTPS',
    value: 3
  }
]
const tlsArray = ['TLSv1.0', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']

const show = async () => {
  showPortInput.value = true
  await nextTick()
  portInputRef.value![0].focus()
}

const httpPortListTop3 = computed(() => httpPortList.value.slice(0, 3))
const httpPortListOther = computed(() => httpPortList.value.slice(3))
const httpsPortListTop3 = computed(() => httpsPortList.value.slice(0, 3))
const httpsPortListOther = computed(() => httpsPortList.value.slice(3))
const handleBlur = () => {
  if (!port.value) {
    port.value = licenseInfo.value?.site_cert?.force_https_port ?? 443
  }
  showPortInput.value = false
}
const getLicenseInfo = (updateSource: boolean = true) => {
  loading.value = true
  getApiSiteCertApi({ id: siteId.value })
    .then((res) => {
      licenseInfo.value = res
      if (!licenseInfo.value.site_cert?.hsts_status) {
        licenseInfo.value.site_cert.hsts_status = 2
      }
      if (updateSource) {
        source.value = res.site_cert?.source ?? 1
      }
      port.value = res?.site_cert?.force_https_port ?? 443
      cname.value = res.cname
      if (
        res.site_cert?.http_status === 1 &&
        res.site_cert?.https_status === 1
      ) {
        protocol.value = 2
      } else if (res.site_cert?.http_status == 1) {
        protocol.value = 1
      } else {
        protocol.value = 3
      }
    })
    .finally(() => {
      loading.value = false
    })
}
const getPortConf = () => {
  getApiConfigHttpPortsApi({ with_default_ports: true }).then((res) => {
    httpPortList.value = res.http ?? []
    httpsPortList.value = res.https ?? []
  })
}
const handleBeforeChange = (status: number, row: SiteLicenseModel) => {
  const data: any = {
    id: siteId.value,
    hsts_status: status
  }
  return updateApiSiteCertHstsApi(data)
    .then(() => (row.hsts_status = status))
    .finally(() => (saveLoading.value = false))
}
const saveLoading = ref(false)
/**
 * 保存站点证书信息
 *
 * @returns {Promise<void>} 返回一个 Promise 对象，Promise 解析后执行成功提示并获取许可证信息
 */
const handleSave = () => {
  saveLoading.value = true
  const data: any = {
    id: siteId.value,
    source: source.value,
    http_status: protocol.value !== 3 ? 1 : 2,
    https_status: protocol.value !== 1 ? 1 : 2,
    force_https_port: port.value
  }
  return updateApiSiteCertApi(data)
    .then(() => {
      ToastUtils.success('操作成功')
      getLicenseInfo()
    })
    .finally(() => (saveLoading.value = false))
}

watchEffect(() => {
  getLicenseInfo()
})

provide(licenseInfoKey, licenseInfo)
provide(uploadLicenseKey, openUpload)

onMounted(() => {
  getPortConf()
})
</script>

<style lang="less">
.license-agreement {
  @apply flex flex-col gap-y-4;
  .system-tag {
    height: 20px;
    border-radius: 8px 1px;
    padding: 2px 6px;
    margin-left: 4px;
  }

  .protocol-radio {
    @apply grid grid-rows-1 grid-cols-3 mt-2;
    .arco-radio {
      padding-left: 0;
    }
  }
  .title {
    width: 90px;
    margin-right: 24px;
    @apply text-2  text-sm/22px;
  }
  .subtitle {
    line-height: 22px !important;
    @apply text-5 leading-24px text-xs;
  }

  .agreement-content {
    display: flex;
  }
  .agreement-array {
    display: flex;
    align-items: center;
    gap: 24px;
    .agreement-array-row {
      display: flex;
      align-items: center;
      .agreement-array-key {
        overflow: hidden;
        color: var(----2color-text-5, #a6adb8);
        text-overflow: ellipsis;
        font-size: 12px;
        line-height: 20px; /* 166.667% */
      }
      .agreement-array-value {
        display: flex;
        align-items: center;
        gap: 6px;
        .agreement-array-item {
          display: flex;
          height: 20px;
          padding: 0px 6px;
          align-items: center;
          border-radius: 2px;
          background: var(---color-fill-2, #f2f3f5);
          color: var(----1color-text-4, #8f959e);
          font-size: 12px;
          line-height: 20px; /* 166.667% */
        }
      }
      .agreement-more {
        user-select: none;
        &:hover {
          cursor: pointer;
          border-radius: 2px;
          background: var(---color-fill-3, #e5e6eb);
        }
      }
    }
  }

  .custom-radio-card {
    display: flex;
    flex-direction: column;
    row-gap: 4px;
    flex: 1;
    height: 72px;
    border-radius: 8px;
    border: 1px solid var(---color-border-4, #dfe2e5);
    padding: 12px 16px;
    &-checked {
      border: 1px solid var(---primary-6, #165dff);
      background: var(---primary-1, #e8f3ff);
    }
  }
  .change-port {
    @apply text-primary cursor-pointer;
  }
}
.custom-tooltip {
  display: flex;
  padding: 12px 16px;
  align-items: flex-start;
  align-content: flex-start;
  gap: 8px;
  flex-wrap: wrap;
  border-radius: 4px;
  border: 1px solid var(---color-border-2, #eeeff2);
  background: var(---color-bg-white, #fff);
  box-shadow: 0px 4px 10px 0px rgba(29, 33, 41, 0.1);
  .agreement-array-item {
    display: flex;
    height: 20px;
    padding: 0px 6px;
    align-items: center;
    border-radius: 2px;
    background: var(---color-fill-2, #f2f3f5);
    color: var(----1color-text-4, #8f959e);
    font-size: 12px;
    line-height: 20px; /* 166.667% */
  }
}
.arco-trigger-arrow {
  border: 1px solid var(---color-border-2, #eeeff2);
  z-index: 1;
}
</style>
